package com.zbkj.service.service.impl;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.zbkj.common.constants.*;
import com.zbkj.common.exception.AppException;
import com.zbkj.common.model.bill.Bill;
import com.zbkj.common.model.member.PaidMemberOrder;
import com.zbkj.common.model.monitor.ZfbMonitorOrder;
import com.zbkj.common.model.order.MonitorOrder;
import com.zbkj.common.model.order.Order;
import com.zbkj.common.model.order.OrderDetail;
import com.zbkj.common.model.order.RechargeOrder;
import com.zbkj.common.model.user.User;
import com.zbkj.common.request.MonitorOrderFrontSaveRequest;
import com.zbkj.common.request.MonitorOrderSaveRequest;
import com.zbkj.common.request.MonitorOrderSearchRequest;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.response.*;
import com.zbkj.common.result.CommonResultCode;
import com.zbkj.common.utils.CrmebDateUtil;
import com.zbkj.common.utils.CrmebUtil;
import com.zbkj.service.dao.MonitorOrderDao;
import com.zbkj.service.service.*;
import com.zbkj.service.util.BrandUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

/**
 * 活动样式
 *
 * @author dazongzi
 * @description ActivityStyleServiceImpl 接口实现
 * @date 2023-01-05
 */
@Service
public class MonitorOrderServiceImpl extends ServiceImpl<MonitorOrderDao, MonitorOrder> implements MonitorOrderService {
    @Resource
    private MonitorOrderDao dao;

    @Autowired
    private UserService userService;

    @Autowired
    private MerchantService merchantService;

    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private OrderStatusService orderStatusService;

    @Override
    public Boolean create(MonitorOrderSaveRequest monitorOrderSaveRequest) {
        return null;
    }

    @Override
    public List<MonitorOrderPageDataResponse> getList(MonitorOrderSearchRequest request, PageParamRequest pageParamRequest) {
        PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());

        //带 ShortplayItems 类的多条件查询
        LambdaQueryWrapper<MonitorOrder> lambdaQueryWrapper = Wrappers.lambdaQuery();

        if (StrUtil.isNotBlank(request.getOrderNo())) {
            lambdaQueryWrapper.eq(MonitorOrder::getOrderNo, request.getOrderNo().trim());
        }

        if (ObjectUtil.isNotEmpty(request.getOrderStatus())) {
            lambdaQueryWrapper.eq(MonitorOrder::getOrderStatus, request.getOrderStatus());
        }

        if (ObjectUtil.isNotEmpty(request.getPayChannel())) {
            lambdaQueryWrapper.eq(MonitorOrder::getPayChannel, request.getPayChannel());
        }

        if (ObjectUtil.isNotEmpty(request.getPayType())) {
            lambdaQueryWrapper.eq(MonitorOrder::getPayType, request.getPayType());
        }

        if (ObjectUtil.isNotEmpty(request.getLinkType())) {
            lambdaQueryWrapper.eq(MonitorOrder::getLinkType, request.getLinkType());
        }

        if (StrUtil.isNotBlank(request.getMerchantName())) {
            lambdaQueryWrapper.like(MonitorOrder::getMerchantName, request.getMerchantName().trim());
        }

        lambdaQueryWrapper.orderByAsc(MonitorOrder::getCreateTime);
        List<MonitorOrder> shortplayItemss = dao.selectList(lambdaQueryWrapper);
        List<MonitorOrderPageDataResponse> list = new ArrayList<>();

        shortplayItemss.stream().forEach(x->{
            MonitorOrderPageDataResponse response = new MonitorOrderPageDataResponse();
            BeanUtils.copyProperties(x, response);
            list.add(response);
        });
        return list;
    }

    @Override
    public List<MonitorOrderFrontSearchResponse> getListFront(MonitorOrderSearchRequest request, PageParamRequest pageParamRequest) {
        PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());

        //带 ShortplayItems 类的多条件查询
        LambdaQueryWrapper<MonitorOrder> lambdaQueryWrapper = Wrappers.lambdaQuery();

        if (StrUtil.isNotBlank(request.getOrderNo())) {
            lambdaQueryWrapper.eq(MonitorOrder::getOrderNo, request.getOrderNo().trim());
        }

        if (ObjectUtil.isNotEmpty(request.getOrderStatus())) {
            lambdaQueryWrapper.eq(MonitorOrder::getOrderStatus, request.getOrderStatus());
        }

        if (ObjectUtil.isNotEmpty(request.getPayChannel())) {
            lambdaQueryWrapper.eq(MonitorOrder::getPayChannel, request.getPayChannel());
        }

        if (ObjectUtil.isNotEmpty(request.getPayType())) {
            lambdaQueryWrapper.eq(MonitorOrder::getPayType, request.getPayType());
        }

        if (ObjectUtil.isNotEmpty(request.getLinkType())) {
            lambdaQueryWrapper.eq(MonitorOrder::getLinkType, request.getLinkType());
        }

        if (StrUtil.isNotBlank(request.getMerchantName())) {
            lambdaQueryWrapper.like(MonitorOrder::getMerchantName, request.getMerchantName().trim());
        }

        lambdaQueryWrapper.orderByAsc(MonitorOrder::getCreateTime);
        List<MonitorOrder> shortplayItemss = dao.selectList(lambdaQueryWrapper);
        // 添加活动状态
        List<MonitorOrderFrontSearchResponse> list = new ArrayList<>();

        shortplayItemss.stream().forEach(x->{
            MonitorOrderFrontSearchResponse response = new MonitorOrderFrontSearchResponse();
            BeanUtils.copyProperties(x, response);
            list.add(response);
        });
        return list;
    }

    @Override
    public MonitorOrderDetailResponse getDetailById(Integer id) {
        MonitorOrder monitorOrder = getByIdException(id);
        MonitorOrderDetailResponse response = new MonitorOrderDetailResponse();
        BeanUtils.copyProperties(monitorOrder, response);
        return response;
    }

    @Override
    public MonitorOrder getByOutTradeNo(String outTradeNo) {
        LambdaQueryWrapper<MonitorOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(MonitorOrder::getOutTradeNo, outTradeNo);
        lqw.eq(MonitorOrder::getIsDel, false);
        lqw.last(" limit 1");
        return dao.selectOne(lqw);
    }

    @Override
    public boolean deleteById(Integer id) {
        MonitorOrder shortplayItems = getByIdException(id);
        shortplayItems.setIsDel(true);
        boolean update = updateById(shortplayItems);
        if (!update) {
            throw new AppException(CommonResultCode.ERROR.setMessage("删除监控订单失败"));
        }
        return true;
    }

    @Override
    public MonitorOrder getByMerchantName(String merchantName) {
        LambdaQueryWrapper<MonitorOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(MonitorOrder::getMerchantName, merchantName);
        lqw.eq(MonitorOrder::getIsDel, false);
        lqw.orderByDesc(MonitorOrder::getCreateTime);
        lqw.last(" limit 1");
        return dao.selectOne(lqw);
    }

    @Override
    public OrderNoResponse createOrder(MonitorOrderFrontSaveRequest request) {
        User user = userService.getInfo();
        // 获取品牌商收费设置
        MerchantSettledConfigResponse regConfigBrand = merchantService.getMerchantSettledConfig();
        if (!BooleanUtil.isTrue(regConfigBrand.getIsRegRecharge())) {
            throw new AppException(CommonResultCode.VALIDATE_FAILED, "无法下单，品牌商已设置为免费策略");
        }
        MonitorOrder monitorOrder = new MonitorOrder();
        monitorOrder.setUserId(user.getId());
        monitorOrder.setLinkId(request.getMerchantApplyId());
        monitorOrder.setLinkType(1);
        BigDecimal productPrice = BigDecimal.ZERO;
        String productName = "";
        switch (request.getGroupType()) {
            case 0:
                productPrice = regConfigBrand.getLevel2YearPrice();
                monitorOrder.setProTotalPrice(regConfigBrand.getLevel2YearPrice().multiply(new BigDecimal(request.getPayNum())));
                productName = "2年监控流量套餐";
                break;
            case 1:
                productPrice = regConfigBrand.getLevel5YearPrice();
                monitorOrder.setProTotalPrice(regConfigBrand.getLevel5YearPrice().multiply(new BigDecimal(request.getPayNum())));
                productName = "5年监控流量套餐";
                break;
            case 2:
                productPrice = regConfigBrand.getLifelongPrice();
                monitorOrder.setProTotalPrice(regConfigBrand.getLifelongPrice().multiply(new BigDecimal(request.getPayNum())));
                productName = "终身监控流量套餐";
                break;
            case 3:
                productPrice = regConfigBrand.getLevel3YearPrice();
                monitorOrder.setProTotalPrice(regConfigBrand.getLevel3YearPrice().multiply(new BigDecimal(request.getPayNum())));
                productName = "3年监控流量套餐";
                break;
        }
        // 四舍五入
        monitorOrder.setProTotalPrice(monitorOrder.getProTotalPrice().setScale(2, BigDecimal.ROUND_UP));
        monitorOrder.setTotalPrice(monitorOrder.getProTotalPrice());

        monitorOrder.setPayPrice(monitorOrder.getProTotalPrice());
        monitorOrder.setProductName(productName);

        Order order = new Order();
        if (user.getBrandId() != 0) {
            String orderNo = CrmebUtil.getOrderNo(OrderConstants.ORDER_PREFIX_BRAND);
            order.setOrderNo(orderNo);
            order.setLevel(OrderConstants.ORDER_LEVEL_BRAND);
        }else{
            String orderNo = CrmebUtil.getOrderNo(OrderConstants.ORDER_PREFIX_PLATFORM);
            order.setOrderNo(orderNo);
            order.setLevel(OrderConstants.ORDER_LEVEL_PLATFORM);
        }
        // 因为监控流量充值属于平台订单，所以这里不设置商户id
        order.setMerId(0);
        order.setUid(user.getId());
        order.setTotalNum(1);
        order.setTotalPostage(BigDecimal.ZERO);
        order.setSvipDiscountPrice(BigDecimal.ZERO);
        order.setTotalPrice(monitorOrder.getPayPrice());
        order.setCouponPrice(BigDecimal.ZERO);
        order.setUseIntegral(0);
        order.setIntegralPrice(BigDecimal.ZERO);
        order.setPayPrice(monitorOrder.getPayPrice());
        order.setPayPostage(BigDecimal.ZERO);
        order.setPaid(false);
        order.setCancelStatus(OrderConstants.ORDER_CANCEL_STATUS_NORMAL);
        // 监控流量充值订单
        order.setType(OrderConstants.ORDER_TYPE_MONITOR_REG);
        order.setMerCouponPrice(BigDecimal.ZERO);
        order.setPlatCouponPrice(BigDecimal.ZERO);
        order.setIsSvip(user.getIsPaidMember());

        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setOrderNo(order.getOrderNo());
        // 因为监控流量充值属于平台订单，所以这里不设置商户id
        orderDetail.setMerId(0);
        orderDetail.setUid(user.getId());
        orderDetail.setProductId(0);
        orderDetail.setProductName(monitorOrder.getProductName());
        orderDetail.setAttrValueId(0);
        orderDetail.setSku("监控流量充值");
        orderDetail.setPrice(monitorOrder.getPayPrice());
        orderDetail.setPayNum(1);
        orderDetail.setWeight(BigDecimal.ZERO);
        orderDetail.setVolume(BigDecimal.ZERO);
        orderDetail.setProductType(ProductConstants.PRODUCT_TYPE_MONITOR_REG);
        orderDetail.setSubBrokerageType(0);
        orderDetail.setBrokerage(0);
        orderDetail.setBrokerageTwo(0);
        orderDetail.setFreightFee(BigDecimal.ZERO);
        orderDetail.setUseIntegral(0);
        orderDetail.setIntegralPrice(BigDecimal.ZERO);
        orderDetail.setPayPrice(monitorOrder.getPayPrice());

        orderDetail.setIsSvip(order.getIsSvip());
        orderDetail.setIsPaidMemberProduct(false);
        orderDetail.setVipPrice(BigDecimal.ZERO);

        orderDetail.setMerCouponPrice(BigDecimal.ZERO);
        orderDetail.setPlatCouponPrice(BigDecimal.ZERO);
        orderDetail.setCouponPrice(BigDecimal.ZERO);
        orderDetail.setImage("");
        orderDetail.setPrice(productPrice);

        monitorOrder.setPrice(productPrice);
        monitorOrder.setOrderNo(order.getOrderNo());
        // 0待支付 1已支付
        monitorOrder.setOrderStatus(0);
        monitorOrder.setCreateTime(new Date());
        LocalDateTime startTime = LocalDateTime.now();
        monitorOrder.setStartTime(startTime);
        monitorOrder.setEndTime(getOrderExpireTime(startTime, request));
        monitorOrder.setGroupType(request.getGroupType());
        monitorOrder.setType(1);
        save(monitorOrder);

        orderService.save(order);
        orderDetailService.save(orderDetail);

        // 生成订单日志
        orderStatusService.createLog(order.getOrderNo(), OrderStatusConstants.ORDER_STATUS_CREATE, OrderStatusConstants.ORDER_LOG_MESSAGE_CREATE);

        OrderNoResponse response = new OrderNoResponse();
        response.setOrderNo(order.getOrderNo());
        response.setPayPrice(order.getPayPrice());
        response.setOrderType(OrderConstants.ORDER_TYPE_MONITOR_REG);
        return response;
    }

    @Override
    public void callBack(String orderNo) {
        MonitorOrder monitorOrder = getByOrderNo(orderNo);
        Order order = orderService.getByOrderNo(orderNo);
        monitorOrder.setThirdOrderNo(order.getOutTradeNo());
        monitorOrder.setPayType(order.getPayType());
        monitorOrder.setPayChannel(order.getPayChannel());
        // 0-待支付 1-已支付
        if (Objects.equals(order.getPaid(), true)) {
            monitorOrder.setOrderStatus(1);
        } else {
            monitorOrder.setOrderStatus(0);
        }
        updateById(monitorOrder);
    }

    @Override
    public MonitorOrder getByLinkId(Integer id, int type) {
        LambdaQueryWrapper<MonitorOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(MonitorOrder::getLinkId, id);
        lqw.eq(MonitorOrder::getLinkType, type);
        lqw.eq(MonitorOrder::getIsDel, false);
        lqw.orderByDesc(MonitorOrder::getCreateTime);
        lqw.last(" limit 1");
        return dao.selectOne(lqw);
    }
    @Override
    public BigDecimal getUserMonitorOrderPrice(Integer uid) {
        LambdaQueryWrapper<MonitorOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(MonitorOrder::getUserId, uid);
        lqw.eq(MonitorOrder::getIsDel, false);
        List<MonitorOrder> order = dao.selectList(lqw);
        BigDecimal  orderPrice = order.stream().map(MonitorOrder::getPrice).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        return orderPrice;
    }

    private MonitorOrder getByOrderNo(String orderNo) {
        LambdaQueryWrapper<MonitorOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(MonitorOrder::getOrderNo, orderNo);
        lqw.eq(MonitorOrder::getIsDel, false);
        lqw.orderByDesc(MonitorOrder::getCreateTime);
        lqw.last(" limit 1");
        return dao.selectOne(lqw);
    }

    private MonitorOrder getByIdException(Integer id) {
        MonitorOrder monitorOrder = getById(id);
        if (ObjectUtil.isNull(monitorOrder) || monitorOrder.getIsDel().equals(Constants.COMMON_IS_FILED_ONE)) {
            throw new AppException(CommonResultCode.ERROR.setMessage("监控订单不存在"));
        }
        return monitorOrder;
    }

    /**
     * 支付完成变动
     */
    private boolean updatePaid(Long id, String orderNo) {
        LambdaUpdateWrapper<MonitorOrder> wrapper = Wrappers.lambdaUpdate();
        wrapper.set(MonitorOrder::getOrderStatus, 1);
        wrapper.set(MonitorOrder::getPayTime, CrmebDateUtil.nowDateTime());
        wrapper.eq(MonitorOrder::getId, id);
        wrapper.eq(MonitorOrder::getOrderNo, orderNo);
        wrapper.eq(MonitorOrder::getIsDel, false);
        wrapper.eq(MonitorOrder::getOrderStatus, 0);
        return update(wrapper);
    }

    private LocalDateTime getOrderExpireTime(LocalDateTime startTime, MonitorOrderFrontSaveRequest request) {
        if (request == null) {
            throw new AppException("套餐不存在");
        }

        LocalDateTime endTime = LocalDateTime.now();

        // 1=月 2=季 3=年
        switch (request.getGroupType()) {
            case 0:
                endTime = startTime.plusYears(2);
                break;
            case 1:
                endTime = startTime.plusYears(1);
                break;
            case 2:
                endTime = startTime.plusYears(200);
                break;
            default:
                break;
        }

        return endTime;
    }

}

